/*
 * Copyright (C) 2012 mAPPn.Inc
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.mol.market.ui_v4;

import java.util.ArrayList;
import java.util.HashMap;

import android.os.Bundle;
import android.support.v4.app.LoaderManager.LoaderCallbacks;
import android.support.v4.content.Loader;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;

import com.mol.market.Constants;
import com.mol.market.R;
import com.mol.market.common.network.ApiResponse;
import com.mol.market.common.util.Utils;
import com.mol.market.demo.widget.LazyLoadFragmentWrapper;
import com.mol.market.demo.widget.LazyLoadListFragment;

/**
 * copy from {@link LazyLoadFragmentWrapper}
 * <hr>
 * API请求方式不同，其他一致。
 * @author Chaos
 * @Description 
 *  封装了API请求，采用Loader方式。对ListFragment进行了简单的实现。
 *  如果需要修改布局List，调用{@link #getCommonList(LayoutInflater)} 
 *  <br>
 *  1. API请求完成时，将会回调{@link #onSuccess(int, Object)},{@link #onError(int, int)},
 *  和 {@link #onBusinesLogicError(int)}
 *  <br>
 *  2.如果请求的API不仅仅是List的API，可以调用{@link #filter(int)}
 *  来实现过滤，也可以复写{@link #onLoadFinished(Loader, ApiResponse)}来决定是否调用
 *  父类的此方法。
 * @date 2013-2-6
 */
public abstract class SimpleLazyLoadFragmentLoader extends LazyLoadListFragment
                implements LoaderCallbacks<ApiResponse>{
    
    @Override
    public void onLoadFinished(Loader<ApiResponse> loader, ApiResponse data) {
        
        if(loader == null || data == null || filter(data.action)){
            //如果是无关API的请求，过滤掉不处理
            return ;
        }
        
        if(data.status == ApiResponse.STATUS_OK){
            onSuccess(data.action, data.result);
        }else if(data.status == ApiResponse.STATUS_LOGIC_ERROR){
            onBusinesLogicError(data.action);
        }else{
            onError(data.action, data.status);
        }
    }

    @Override
    public void onLoaderReset(Loader<ApiResponse> loader) {
        //To change body of implemented methods use File | Settings | File Templates.
    }
    
    private int mTotalSize = 0;
    
    private void updateData(ArrayList<HashMap<String, Object>> data){
        //当界面已经destroy时，getAdapter将返回Null。
        //fix bug by Chaos at 2012-12-11
        if(getAdapter() != null){
           getAdapter().addDataList(data);
        }
    }
    
    /**
     * 获得通用的ListView，包含Loading和EmtpyView。
     * @param  LayoutInflater
     * @return 包含ListView的ViewGroup 
     */
    protected ViewGroup getCommonList(LayoutInflater inflater){
        return (ViewGroup) inflater.inflate(R.layout.common_list_view_new_loading, null);
    }
    
    /**
     * 如果数据不是<b>HashMap</b>或者条数信息不存在<b>Map</b>中，
     * 复写此方法，并调用{@link #setTotalSize(int)}来设置总条数。
     * 可以调用 {@link #checkAlreadySetTotalSize()}来增加效率.
     * @param  Response
     */
    @SuppressWarnings("unchecked")
    protected void setTotalSizeIfNeed(Object data){
        
        if(checkAlreadySetTotalSize()){
            return ;
        }
        
        if(data instanceof HashMap){
            Object item = ((HashMap<String, Object>) data).get(getSizeKey());
            if (item != null) {
                mTotalSize = Utils.getInt(item.toString());
            }
        }
        
        setTotal(mTotalSize);
    }
    
    protected boolean checkAlreadySetTotalSize() {
        return mTotalSize != 0;
    }
    
    /**
     * 如果item总条数的Key不为{@link Constants#KEY_TOTAL_SIZE},
     * 则复写此方法。
     * @return item总条数对应的Key
     * @throws
     */
    protected String getSizeKey() {
        return Constants.KEY_TOTAL_SIZE;
    }
    
    /**
     * 获得将要展示的View<hr>
     * note:必须包含 ID为 <b>@android:id/list</b>的<b>AbsListView</b>
     * 或者包含{@link #getCommonList(LayoutInflater)}
     * @param LayoutInflater
     * @return 最终显示的View
     */
    protected ViewGroup getRootView(LayoutInflater inflater){
        return getCommonList(inflater);
    }
    
    /**
     * 从结果中取得数据
     * @param Response
     * @return ArrayList<HashMap<String,Object>> 数据将被追加到Adapter中
     */
    protected abstract ArrayList<HashMap<String, Object>> getDataFromResult(int method,Object obj);

    /**
     * 子类若Override的此方法，应该首先调用
     * <code>super.onSuccess(int,Object) </code>
     */
    public void onSuccess(int method, Object obj) {
        setTotalSizeIfNeed(obj);
        updateData(getDataFromResult(method,obj));
        loadSuccess();
    }
    /**
     * 子类若Override的此方法，应该首先调用
     * <code>super.onError(int,Object) </code>
     */
    public void onError(int method, int statusCode) {
        loadFailure();
    }
    
    /**
     * 业务逻辑异常，当发生业务逻辑时，调用此方法。
     * <hr>
     * 默认调用 {@link #onError(method, ApiResponse.STATUS_LOGIC_ERROR)} 处理，
     * 子类可以调用此方法进行特殊处理。
     */
    protected void onBusinesLogicError(int method){
        onError(method, ApiResponse.STATUS_LOGIC_ERROR);
    }    
    
    /**
     * 过滤器，根据请求不同，决定是否对Adapter进行操作，以及控制界面是否正常显示。
     * {@link #onSuccess(int, Object)} and {@link #onError(int, int)}
     * @return 返回true就过滤掉请求
     * <br>
     * 默认不过滤
     */
    protected boolean filter(int method){
        return false;
    }
    
    @Override
    protected final View initLayout(LayoutInflater inflater, ViewGroup container,
            Bundle savedInstanceState) {
        return getRootView(inflater);
    }
    
    @Override
    protected void dealloc() {
        mTotalSize = 0;
        super.dealloc();
    }
    
    @Override
    protected void reset() {
        mTotalSize = 0;
        super.reset();
    }

}
